<?php if(! defined('HAS_POWER') ) exit('无权访问!');
/**
==============================================================================
 * Class ValidateComponent GracePHP的内置表单验证类
 * @author 肖永标
 * @date 2014-12-02
==============================================================================
 */
class ValidateComponent extends Component{

    /**
     * @var FormComponent 表单模型
     */
    protected $form;

    /** 构造函数
     * @param FormComponent $form 表单模型
     */
    public function __construct(FormComponent $form)
    {
        $this->form = $form;
    }

    /** 长度验证
     * @param int $min  最小位数
     * @param int $max  最大位数
     * @throws Exception
     */
    public function length($min, $max='')
    {
        if($max != '')
        {

            if(strpos($min, '.') !== false || !is_numeric($min)
                || strpos($max, '.') !== false || !is_numeric($max))
            {
                throw new Exception('length验证方法必须传入整数参数');
            }

            if(mb_strlen($this->form->val, 'utf-8') < $min || mb_strlen($this->form->val, 'utf-8') > $max)
            {
                $this->_formatMsg('lengthErr', 
                    array(
                        '%min' => $min,
                        '%max' => $max    
                    )
                );
            }
        }
        else 
        {
            if(strpos($min, '.') !== false || !is_numeric($min))
                throw new Exception('length验证方法必须传入整数参数');

            if(mb_strlen($this->form->val, 'utf-8') < $min)
            {
                $this->_formatMsg('lengthMinErr', 
                    array(
                        '%min' => $min,  
                    )
                );
            }
        }
    }

    /**
     * 验证是否是数字
     */
    public function number()
    {
        if(!is_numeric($this->form->val))
            $this->_formatMsg('numberErr');
    }

    /**
     * 验证是否是邮件
     */
    public function email()
    {
        $pattern = '/^([0-9A-Za-z\\-_\\.]+)@([0-9a-z]+\\.[a-z]{2,3}(\\.[a-z]{2})?)$/i';
        
        if(!preg_match($pattern, $this->form->val))
            $this->_formatMsg('emailErr');
    }

    /**
     * 验证是否是url
     */
    public function url()
    {
        $pattern = '/(http|https|ftp|file){1}(:\/\/)?([\da-z-\.]+)\.([a-z]{2,6})([\/\w \.-?&%-=]*)*\/?/';

        if(!preg_match($pattern, $this->form->val))
            $this->_formatMsg('urlErr');
    }

    /** 是否和指定的字段对应
     * @param string $field 要对比的字段
     * @throws Exception
     */
    public function equal($field)
    {
        if($this->form->val !== $this->form->post($field)) 
        {
            $label = $this->form->getLabelByField($field);

            if($label === false)
                throw new Exception('equal验证方法传入的' . $field . '字段不存在');

            $this->_formatMsg('equalErr', 
                array(
                    '%field' => $label
                )
            );        
        }       
    }

    /** 判断是否有选择一个下拉项
     * @param mixed $errVal 触发错误的下拉项值
     */
    public function select($errVal)
    {
        if($this->form->val == $errVal)
            $this->_formatMsg('selectErr');
    }

    /**
     * 验证字段是否填写
     */
    public function required()
    {
        if($this->form->val == '')
            $this->_formatMsg('requiredErr');   
    }

    /** 字段是否等于某个值
     * @param mixed $val
     */
    public function match($val)
    {
        if($this->form->val != $val)
            $this->_formatMsg('matchErr',
                array(
                    '%val' => $val
                )
            );
    }

    /**
     * 是否为整数
     */
    public function integer()
    {
        if(strpos($this->form->val, '.') !== false || !is_numeric($this->form->val))
            $this->_formatMsg('integerErr');
    }

    /** 检查字段是否在某个范围内
     * @param int $start 范围起始值
     * @param int $end 范围结束值
     * @throws Exception
     */
    public function between($start, $end)
    {
        if(!is_numeric($start) || !is_numeric($end))
            throw new Exception('between验证方法必须传入两个整数');

        if($this->form->val < $start || $this->form->val > $end)
        {
            $this->_formatMsg('betweenErr', 
                array(
                    '%start' => $start,
                    '%end' => $end
                )
            );
        }
    }

    /** 格式化错误信息
     * @param string $key 错误信息指定的键值
     * @param array $replace 替换的键值对
     */
    protected function _formatMsg($key, $replace=array())
    {
        $msg = $GLOBALS['msg'][$key];
        
        // 格式化label
        $msg = str_replace('%label', $this->form->label, $msg);    

        // 键值对对应格式化字符串
        foreach ($replace as $format => $string)
        {
            $msg = str_replace($format, $string, $msg);                   
        }  

        $this->form->setError($msg);        
    }

    public function allowLoad()
    {
        return false;
    }
}
